Coverage Report

Created: 2026-08-07 16:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\cssh-rs\cssh-rs\xtask\src\cross_build\mod.rs
Line
Count
Source
1
//! Cross-build dispatch for cssh-rs.
2
//!
3
//! Single contributor-facing entry point - `cargo xtask cross-build <target>` -
4
//! for producing a cssh-rs binary for any supported target from any
5
//! supported host. The xtask owns the toolchain selection so the
6
//! developer experience does not drift over time.
7
//!
8
//! [`run_cross_build`] orchestrates the workflow: host detection,
9
//! Rust target install, helper-tool install, and the final build
10
//! subprocess. Per-target details (strategy + I/O) live in the
11
//! [`strategy`] and [`system`] submodules.
12
13
pub mod strategy;
14
pub mod system;
15
16
use std::sync::LazyLock;
17
18
use anyhow::Result;
19
use clap::ValueEnum;
20
use cssh_rs_meta::PACKAGE_NAME;
21
22
pub use system::{CrossBuildSystem, RealSystem};
23
24
static X86_64_PC_WINDOWS_MSVC_BINARY: LazyLock<String> =
25
0
    LazyLock::new(|| format!("{PACKAGE_NAME}.exe"));
26
27
/// Supported cross-build target triples.
28
///
29
/// v1 supports one target, `x86_64-pc-windows-msvc` (the only target
30
/// cssh-rs currently ships). Adding a target later is additive: extend
31
/// this enum, extend [`Target::triple`] / [`Target::binary_filename`],
32
/// add a `strategy::<target>` submodule with a `build` entry point,
33
/// and add a dispatch arm in [`run_cross_build`].
34
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
35
pub enum Target {
36
    /// `x86_64-pc-windows-msvc` (production Windows target).
37
    #[value(name = "x86_64-pc-windows-msvc")]
38
    X86_64PcWindowsMsvc,
39
}
40
41
impl Target {
42
    /// Return the Rust target triple this variant maps to.
43
    ///
44
    /// # Returns
45
    /// The canonical `--target` string passed to `cargo`.
46
11
    pub fn triple(self) -> &'static str {
47
11
        match self {
48
11
            Self::X86_64PcWindowsMsvc => "x86_64-pc-windows-msvc",
49
        }
50
11
    }
51
52
    /// Return the executable filename cargo emits for this target,
53
    /// including any platform-specific extension (e.g. `.exe`).
54
0
    pub fn binary_filename(self) -> &'static str {
55
0
        match self {
56
0
            Self::X86_64PcWindowsMsvc => X86_64_PC_WINDOWS_MSVC_BINARY.as_str(),
57
        }
58
0
    }
59
}
60
61
/// Cross-build cssh-rs for the given target.
62
///
63
/// # Arguments
64
/// * `system` - Injected I/O provider.
65
/// * `target` - The user-selected target.
66
/// * `release` - When true, build with `--release`; otherwise debug.
67
///
68
/// # Errors
69
/// Returns an error if the (host, target) pair is unsupported, a
70
/// toolchain install fails, or the build subprocess fails.
71
10
pub fn run_cross_build<S>(system: &S, target: Target, release: bool) -> Result<()>
72
10
where
73
10
    S: system::windows_msvc::WindowsMsvcSystem,
74
{
75
10
    let host = system.host_os();
76
10
    let triple = target.triple();
77
10
    let profile = if release { 
"release"2
} else {
"debug"8
};
78
10
    log::info!("Cross-building {triple} from {host} host ({profile} profile)");
79
80
10
    match target {
81
10
        Target::X86_64PcWindowsMsvc => strategy::windows_msvc::build(system, release)
?3
,
82
    }
83
84
7
    log::info!(
85
        "Binary built: target/{triple}/{profile}/{}",
86
0
        target.binary_filename()
87
    );
88
7
    Ok(())
89
10
}
90
91
/// Ensure the given Rust target triple is installed via rustup.
92
///
93
/// Shared by every per-target strategy; install is a single
94
/// `rustup target add` if the triple is not already listed.
95
9
pub(crate) fn ensure_rust_target_installed<S: CrossBuildSystem>(
96
9
    system: &S,
97
9
    triple: &str,
98
9
) -> Result<()> {
99
9
    let installed = system.list_installed_targets()
?0
;
100
9
    if installed.lines().any(|line| line.trim() == triple) {
101
8
        log::info!("Rust target {triple} already installed");
102
    } else {
103
1
        log::info!("Installing Rust target {triple}");
104
1
        system.install_target(triple)
?0
;
105
    }
106
9
    Ok(())
107
9
}
108
109
#[cfg(test)]
110
#[path = "../tests/test_cross_build.rs"]
111
mod tests;